
// 禁止类型转换警告
#![allow(overflowing_literals)]

use std::convert::TryFrom;
use std::convert::TryInto;
use std::str::FromStr;
use std::num::ParseIntError;

/// 变量， 类型， 转换
fn main() {


    let an_integer = 1u32;
    let a_boolean = true;
    let unit = ();

    let copied_integer = an_integer;

    println!("An integer: {:?}", copied_integer);
    println!("A boolean: {:?}", a_boolean);
    println!("Meet the unit value: {:?}", unit);

    // 下划线起始的变量，编译器可以不提示未使用的警告
    let _unused_integer = 2u32;


    let mut mutable_var = 1u32;
    mutable_var += 1;
    println!("mutable var:-- {}", mutable_var);


    // 变量作用域： {}为一个块级作用域。
    let mut long_lived_binding = 1;
    println!("before long: {}", long_lived_binding);

    {
        let short_lived_binding = 2;
        println!("inner short: {}", short_lived_binding);
    }

    // 此处，上面块级作用域里的变量。
    // println!("outer short: {}", short_lived_binding);

    // 重新覆写
    let short_lived_binding = 3;
    println!("overwrite short: {}", short_lived_binding);
    long_lived_binding = 4;
    println!("after long: {}", long_lived_binding);


    // 类型转换 as
    let decimal = 65.4321_f32;

    // rust不提供原始类型的隐式转换，使用as强制转换。
    // let integer: u8 = decimal;

    // Explicit conversion
    let integer = decimal as u8;
    let character = integer as char;
    // 浮点数转换字符类型，不支持
    // let character = decimal as char;
    println!("Casting: {} -> {} -> {}", decimal, integer, character);

    // 255
    println!("300.0 is {}", 300.0_f32 as u8);
    //  0
    println!("-100.0 as u8 is {}", -100.0_f32 as u8);
    //  0
    println!("nan as u8 is {}", f32::NAN as u8);

    // unsafe ：小的运行时成本，但有可能导致错误的输出。
    unsafe {
        // 44
        println!("300.0 is {}", 300.0_f32.to_int_unchecked::<u8>());
        // 156
        println!("-100.0 as u8 is {}", (-100.0_f32).to_int_unchecked::<u8>());
        // 0
        println!("nan as u8 is {}", f32::NAN.to_int_unchecked::<u8>());
    }


    // 如果不存在约束，编译器将i32用于整数和f64浮点数。
    let x = 1u8;
    let y = 2u32;
    let z = 3f32;
    let i = 1;
    let f = 1.0;
    println!("size of `x` in bytes: {}", std::mem::size_of_val(&x));
    println!("size of `y` in bytes: {}", std::mem::size_of_val(&y));
    println!("size of `z` in bytes: {}", std::mem::size_of_val(&z));
    println!("size of `i` in bytes: {}", std::mem::size_of_val(&i));
    println!("size of `f` in bytes: {}", std::mem::size_of_val(&f));

    // 编译器-类型推导
    let elem = 5u8;
    let mut vec = Vec::new();
    vec.push(elem);
    println!("vec:{:?}", vec);

    // 类型别名
    #[allow(non_camel_case_types)]
    type int = i32;   //类型名首字母大写
    type Int = i32;
    let a:Int = 1;
    let b:int = 2;
    println!("a = {:?}", a);
    println!("b = {:?}", b);

    // 结构体转换 Trait： From  Into
    // From : 最常见的 String::from()
    let my_str = "hello";
    let my_string = String::from(my_str);
    println!("String - {:?}", my_string);

    // From conversion
    let num = Number::from(666);
    println!("My number is {:?}", num);

    // Into
    {
        let int = 5;
        let num: Number = int.into();
        println!("My number is {:?}", num);
    }

    {
        let float = 1.1;
        let number: Number = float.into();
        println!("My number is {:?}", number);
    }

    // TryFrom & TryInto
    // 用户错误转换， 返回Result
    {
        let uu: u8 = 1;
        let number = Number::try_from(uu);
        let into_number:Result<Number, _> = 5u8.try_into();
        let into_err_number:Result<Number, &'static str> = 0u8.try_into();
        println!("My TryFrom number is {:?}", number);
        println!("My TryInto number is {:?}", into_number);
        println!("My TryInto error number is {:?}", into_err_number);
    }


    // 字符串转换
    // Display Trait
    {
        struct Circle {
            radius: i32
        }

        impl std::fmt::Display for Circle {
            fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
                write!(f, "Circle of radius {}", self.radius)
            }
        }

        let circle = Circle { radius: 6 };
        println!("Circle to string:{}", circle.to_string());
    }

    // 字符串转换成数字
    {
        let parse_int: i32 = "10086".parse().unwrap_or(0);
        let parse_int2 = "13".parse::<i32>().unwrap_or(0);
        println!("parse int1 is: {}", parse_int);
        println!("parse int2 is: {}", parse_int2);
    }


    // 字符串 复合类型转换
    // FromStr trait
    {
        let num = Number::from_str("{value:123}");
        println!("num is: {:?}", num.unwrap());
    }

}

#[allow(dead_code)]
#[derive(Debug)]
struct Number {
    value: i32,
}

impl std::convert::From<i32> for Number {
    fn from(val: i32) -> Self {
        Number { value: val}
    }
}

impl std::convert::From<f32> for Number {
    fn from(val: f32) -> Self {
        Number { value: val as i32}
    }
}

impl TryFrom<u8> for Number {
    type Error = &'static str;
    fn try_from(value: u8) -> Result<Self, Self::Error> {
        if value <= 0 {
            Err("此处需要大于0的u8数据")
        } else {
            Ok( Number { value: value  as i32})
        }
    }
}


impl FromStr for Number {
    type Err = ParseIntError;
    fn from_str(s: &str) -> Result<Self, Self::Err>{
        let coords: Vec<&str> = s.trim_matches(|p| p == '{' || p == '}' )
                                 .split(':')
                                 .collect();
        // let field = coords[0];
        let value = coords[1].parse::<i32>()?;
        Ok(Number {value: value})
    }
}